package com.yz.kronos.executor.trigger;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.yz.kronos.common.TriggerData;
import com.yz.kronos.executor.ContextExecutor;
import com.yz.kronos.executor.context.ExecutorContext;
import com.yz.kronos.executor.exception.TriggerException;
import org.springframework.beans.BeansException;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 基础的触发器
 * kronos.trigger.param={"clazz":"com.yz.kronos.demo.service.DemoService","method":"test","index":0,"shareTotal":2,"extend":"1111111111"}
 * @author shanchong
 * @date 2021/11/22
 **/
public abstract class AbstractTrigger implements Trigger, ApplicationListener<ApplicationStartedEvent> {

    @Override
    public void onApplicationEvent(final ApplicationStartedEvent applicationStartedEvent) {
        ConfigurableApplicationContext applicationContext = applicationStartedEvent.getApplicationContext();
        // 接收触发的类和方法
        String triggerParams = getTriggerParams();
        if (triggerParams == null || "".equals(triggerParams)) {
            throw new TriggerException("Not found trigger params.");
        }
        // 解析触发的类和方法,触发
        Gson gson = new GsonBuilder().create();
        TriggerData triggerData = gson.fromJson(triggerParams, TriggerData.class);
        if (triggerData.getClazz()==null || "".equals(triggerData.getClazz())) {
            throw new TriggerException("Trigger params parse error. not found param:clazz");
        }
        if (triggerData.getMethod()==null || "".equals(triggerData.getMethod())) {
            throw new TriggerException("Trigger params parse error. not found param:method");
        }
        Object bean = applicationContext.getBean(triggerData.getClazz());
        try {
            Method method = bean.getClass().getMethod(triggerData.getMethod());
            if (bean instanceof ContextExecutor) {
                Integer shareTotal = triggerData.getShareTotal();
                Integer index = triggerData.getIndex();
                String extend = triggerData.getExtend();
                ExecutorContext context = new ExecutorContext(shareTotal, index, extend);
                ((ContextExecutor)bean).setContext(context);
            }
            method.invoke(bean);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new TriggerException("Trigger execute error. " + e.getClass() + " message:" + e.getMessage());
        }
    }

}
